package com.rabbitmq.Config;

import com.alibaba.fastjson.JSON;
import com.rabbitmq.Entity.RabbitMQ;
import com.rabbitmq.Entity.RabbitMQInfo;
import com.rabbitmq.Service.JpaService;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

@Configuration
public class RabbitConfig {

    @Autowired
    JpaService jpaService;

    private static Logger logger = LoggerFactory.getLogger(RabbitConfig.class);

    @Bean
    @RefreshScope
    public ConnectionFactory connectionFactory() {
        RabbitMQInfo mqInfo = JSON.parseObject(jpaService.findValueByKey("gs-rabbitmq-info"),RabbitMQInfo.class);
        String host = mqInfo.getHost();
        String port = mqInfo.getPort();
        String username = mqInfo.getUsername();
        String password = mqInfo.getPassword();
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
        connectionFactory.setAddresses(host+":"+port);
        connectionFactory.setUsername(username);
        connectionFactory.setPassword(password);
        connectionFactory.setVirtualHost("/");
        connectionFactory.setPublisherConfirms(true);
        connectionFactory.setPublisherReturns(true);
        logger.info("Create Connection("+ host + ":" + port +")");
        logger.info("用户名："+ username + "，密码：" + password);
        return connectionFactory;
    }

    @Bean
    DirectExchange directExchange() {
        return new DirectExchange(RabbitMQ.EXCHANGE);
    }

    @Bean
    public Queue Queue_HelloString() {
        return new Queue(RabbitMQ.QUEUE_HELLOTOSTRING);
    }

    @Bean
    public Queue Queue_HelloObj() {
        return new Queue(RabbitMQ.QUEUE_HELLOOBJ);
    }

    @Bean
    Binding bindingExchangeA(Queue Queue_HelloString, DirectExchange directExchange) {
        return BindingBuilder.bind(Queue_HelloString).to(directExchange).with(RabbitMQ.ROUTINGKEY_HELLOTOSTRING);
    }

    @Bean
    Binding bindingExchangeB(Queue Queue_HelloObj, DirectExchange directExchange) {
        return BindingBuilder.bind(Queue_HelloObj).to(directExchange).with(RabbitMQ.ROUTINGKEY_HELLOOBJ);
    }

    // 延迟队列
    @Bean
    public DirectExchange Exchange_Delay() {
        return new DirectExchange(RabbitMQ.EXCHANGE_DELAY);
    }

    @Bean
    public Queue Queue_Delay() {
        Map<String, Object> params = new HashMap<>();
        // x-dead-letter-exchange 声明了队列里的死信转发到的DLX名称，
        params.put("x-dead-letter-exchange", RabbitMQ.EXCHANGE_DELAY_INFO);
        // x-dead-letter-routing-key 声明了这些死信在转发时携带的 routing-key 名称。
        params.put("x-dead-letter-routing-key", RabbitMQ.ROUTINGKEY_DELAY_INFO);
        return new Queue(RabbitMQ.QUEUE_DELAY, true, false, false, params);
    }

    @Bean
    public Binding bindingExchangeDelay(Queue Queue_Delay, DirectExchange Exchange_Delay) {
        return BindingBuilder.bind(Queue_Delay).to(Exchange_Delay).with(RabbitMQ.ROUTINGKEY_DELAY);
    }

    // 死信接收队列
    @Bean
    public DirectExchange Exchange_Delay_Info() {
        return new DirectExchange(RabbitMQ.EXCHANGE_DELAY_INFO);
    }

    @Bean
    public Queue Queue_Delay_Info() {
        return new Queue(RabbitMQ.QUEUE_DELAY_INFO, true);
    }

    @Bean
    public Binding bindingExchangeDelayInfo(Queue Queue_Delay_Info, DirectExchange Exchange_Delay_Info) {
        return BindingBuilder.bind(Queue_Delay_Info).to(Exchange_Delay_Info).with(RabbitMQ.ROUTINGKEY_DELAY_INFO);
    }

    @Bean
	public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            @Override
            public void confirm(CorrelationData correlationData, boolean b, String s) {
                logger.info("——————confirm回调——————");
                logger.info("消息唯一标识:" + (correlationData==null?null:correlationData.getId()) + ",确认结果:" + b + ",失败原因:" + s);
            }
        });
        rabbitTemplate.setMandatory(true);
        rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
            @Override
            public void returnedMessage(Message message,
                                        int replyCode,
                                        String replyText,
                                        String exchange,
                                        String routingKey) {
                logger.info("——————return回调——————");
                logger.info("message:" + message + ",replyCode:" + replyCode + ",replyText:" + replyText + ",exchange:" + exchange + ",routingKey:" + routingKey);
            }
        });
        return rabbitTemplate;
    }
}
